/******************************************************************/
/*                                                                */
/*  Winpooch : Windows Watchdog                                   */
/*  Copyright (C) 2004-2005  Benoit Blanchon                      */
/*                                                                */
/*  This program is free software; you can redistribute it        */
/*  and/or modify it under the terms of the GNU General Public    */
/*  License as published by the Free Software Foundation; either  */
/*  version 2 of the License, or (at your option) any later       */
/*  version.                                                      */
/*                                                                */
/*  This program is distributed in the hope that it will be       */
/*  useful, but WITHOUT ANY WARRANTY; without even the implied    */
/*  warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR       */
/*  PURPOSE.  See the GNU General Public License for more         */
/*  details.                                                      */
/*                                                                */
/*  You should have received a copy of the GNU General Public     */
/*  License along with this program; if not, write to the Free    */
/*  Software Foundation, Inc.,                                    */
/*  675 Mass Ave, Cambridge, MA 02139, USA.                       */
/*                                                                */
/******************************************************************/


/******************************************************************/
/* Build configuration                                            */
/******************************************************************/

#define TRACE_LEVEL	2	// warning level


/******************************************************************/
/* Includes                                                       */
/******************************************************************/

// module's interface
#include "FilterSet.h"

// standard headers
#include <tchar.h>

// project's headers
#include "Assert.h"
#include "Trace.h"
#include "Wildcards.h"


/******************************************************************/
/* Internal data types                                            */
/******************************************************************/

typedef struct
{
  int		nFilters ;
  int		nFiltersMax ;
  HFILTER	*pFilters ;
} FILTERSET ;




HFILTERSET FilterSet_Create (int nFiltersMax) 
{
  FILTERSET * p ;

  p = malloc (sizeof(FILTERSET)) ;
  if( ! p ) return NULL ;

  p->nFiltersMax = nFiltersMax ;
  p->nFilters = 0 ;
  
  p->pFilters = calloc (nFiltersMax, sizeof(HFILTER)) ;
  if( ! p->pFilters ) {
    free (p) ;
    return NULL ;
  } 

  // create the first filter : default 
  FilterSet_AddFilter (p, Filter_Create(TEXT("*"))) ;

  return p ;
}


VOID FilterSet_Destroy (HFILTERSET h) 
{
  FILTERSET * p = h ;

  if( ! p ) return ;

  while( p->nFilters-- ) 
    Filter_Destroy (p->pFilters[p->nFilters]) ;

  free (p) ;
}


BOOL FilterSet_AddFilter (HFILTERSET hFilterSet, HFILTER hNewFilter) 
{
  FILTERSET * p = hFilterSet ;
  HFILTER	hExistingFilter ;

  // verify params
  ASSERT (hFilterSet!=NULL) ;
  ASSERT (hNewFilter!=NULL) ;

  TRACE_INFO (TEXT("New = %s\n"), Filter_GetProgram(hNewFilter)) ;
  
  hExistingFilter = FilterSet_GetFilterStrict 
    (hFilterSet, Filter_GetProgram(hNewFilter)) ;
  
  if( hExistingFilter ) 
    {
      TRACE_INFO (TEXT("Found existing\n")) ;

      Filter_Concat (hExistingFilter, hNewFilter) ;
    }
  else
    {
      TRACE_INFO (TEXT("No existing found\n")) ;

      if( p->nFilters >= p->nFiltersMax ) return FALSE ;
      
      p->pFilters[p->nFilters++] = hNewFilter ;
    }

  return TRUE ;
}


HFILTER FilterSet_GetFilter (HFILTERSET hFilterSet, LPCTSTR szProcess) 
{
  int i ;
  FILTERSET * p = hFilterSet ;
  
  // verify params
  ASSERT (hFilterSet!=NULL) ;
  ASSERT (szProcess!=NULL) ;

  for( i=p->nFilters-1 ; i>=0 ; i-- )
    if( Wildcards_Cmp(Filter_GetProgram(p->pFilters[i]),szProcess) )
      return p->pFilters[i] ;

  return NULL ;
}


HFILTER FilterSet_GetFilterStrict (HFILTERSET hFilterSet, LPCTSTR szProcess) 
{
  int i ;
  FILTERSET * p = hFilterSet ;
  
  // verify params
  ASSERT (hFilterSet!=NULL) ;
  ASSERT (szProcess!=NULL) ;

  for( i=p->nFilters-1 ; i>=0 ; i-- )
    if( ! _tcsicmp(Filter_GetProgram(p->pFilters[i]),szProcess) )
      return p->pFilters[i] ;

  return NULL ;
}


UINT FilterSet_GetFilterCount (HFILTERSET hFilterSet) 
{
  FILTERSET * p = hFilterSet ;
  
  // verify params
  ASSERT (hFilterSet!=NULL) ; 
  
  return p->nFilters ;
}


HFILTER FilterSet_GetFilterByNum (HFILTERSET hFilterSet, UINT i) 
{
  FILTERSET * p = hFilterSet ;
  
  // verify params
  ASSERT (hFilterSet!=NULL) ;

  if( i>=p->nFilters ) return NULL ;

  return p->pFilters[i] ;
}

HFILTER FilterSet_GetDefaultFilter (HFILTERSET hFilterSet)
{
  FILTERSET * p = hFilterSet ;

  // verify params
  ASSERT  (hFilterSet!=NULL) ;
  
  return p->pFilters[0] ;
}


VOID FilterSet_RemoveByNum (HFILTERSET hFilterSet, UINT iFilter) 
{
  FILTERSET * p = hFilterSet ;
  HFILTER hFilter ;
  
  // verify params
  ASSERT (hFilterSet!=NULL) ;
  ASSERT (iFilter<p->nFilters) ;

  hFilter = p->pFilters[iFilter] ;
  p->pFilters[iFilter] = p->pFilters[--p->nFilters] ;
}


VOID FilterSet_Remove (HFILTERSET hFilterSet, HFILTER hFilter) 
{
  FILTERSET * p = hFilterSet ;
  int i ;
  
  // verify params
  ASSERT (hFilterSet!=NULL) ;
  
  for( i=0 ; i<p->nFilters ; i++ )
    if( p->pFilters[i]==hFilter )
      break ;

  if( i<p->nFilters ) FilterSet_RemoveByNum (hFilterSet, i) ;
}


BOOL FilterSet_EnumFilters (HFILTERSET hFilterSet, ENUMFILTERSCALLBACK pfnCb, LPVOID pContext) 
{
  FILTERSET * p = hFilterSet ;
  int i ;
  
  // verify params
  ASSERT (hFilterSet!=NULL) ;
  ASSERT (pfnCb!=NULL) ;

  for( i=0 ; i<p->nFilters ; i++ )
    if(! pfnCb (pContext, p->pFilters[i]) )
      break ;

  return TRUE ;
}


BOOL FilterSet_TestPartialKey (HFILTERSET hFilterSet, LPCTSTR szPartialKey) 
{
  FILTERSET	*p = hFilterSet ;
  BOOL		bMatches = FALSE ;
  int		i ;

  // verify params
  ASSERT (hFilterSet!=NULL) ;
  ASSERT (szPartialKey!=NULL) ;

  for( i=0 ; i<p->nFilters && !bMatches ; i++ )
    bMatches = Filter_TestPartialKey (p->pFilters[i], szPartialKey) ;
    
  return bMatches ;
}
